#ifndef __SCHED_SCHED_H_
#define __SCHED_SCHED_H_

#include "astraldef.h"
#include "_2sched.h"
#include "astralapi.h"

void schedm_init();

typedef struct AstralScheduler
{
    int id; //this must be specified by SchedMethod
    void (*minit)();
    /**
     * @brief add ready task into ready queue.
     *
     * @param task ready task.
     */
    void (*madd_ready)(AstralTask task, int core);

    /**
     * @brief remove ready task outof ready queue.
     *
     * @param task ready task.
     * @note ususally used to tansfer task from ready to complete.
     */
    void (*mremove_ready)(AstralTask task);

    /**
     * @brief request a task to run for the specified core.
     *
     * @param core the core who wants a task to run.
     * @return AstralTask the selected task.
     */
    AstralTask (*mpick_next)(int core);

    /**
     * @brief preempt schedule
     * @param task the task which used to compare
     */
    AstralTask (*mtry_next)(int core, AstralTask curr);
    struct AstralScheduler *next;
} *AstralScheduler;

#define DECLARE_SCHEDULER(name) extern struct AstralScheduler name##_scheduler;
#define REGISTER_SCHEDULER(name) &name##_scheduler,

#define DEFINE_SCHEDULER(name, add, remove, pick, try, init)     \
    struct AstralScheduler __attribute__((section("scheduler"))) \
    name##_scheduler = {                                         \
        .id = name,                                              \
        .minit = init,                                           \
        .mpick_next = pick,                                      \
        .madd_ready = add,                                       \
        .mtry_next = try,                                        \
        .mremove_ready = remove};

AstralScheduler next_scheduler();

void mark_need_resched(int core);
void clean_need_resched(int core);
int need_reschedule(int core);
boolean is_sched_disabled(int core);

#ifndef CFG_CORE_NUM
#define CFG_CORE_NUM (1)
#endif

// extern AstralTask gCurrTask[CFG_CORE_NUM];
// extern AstralTask gNextTask[CFG_CORE_NUM];

#endif //__SCHED_SCHED_H_